/**
 * 
 */
package org.mspring.mlog.service.search.impl;

import java.io.Serializable;
import java.util.List;

import org.apache.lucene.search.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.MassIndexer;
import org.hibernate.search.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.mspring.mlog.service.search.BaseHibernateSearch;
import org.mspring.platform.persistence.hibernate.DefaultHibernateTemplate;
import org.mspring.platform.persistence.hibernate.HibernateUtils;
import org.mspring.platform.persistence.support.Page;
import org.mspring.platform.utils.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Gao Youbo
 * @since 2013-1-9
 * @Description
 * @TODO
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
@Service
@Transactional
public class BaseHibernateSearchImpl<T> implements BaseHibernateSearch<T> {

    @Autowired
    private SessionFactory sessionFactory;
    @Autowired
    private DefaultHibernateTemplate hibernateTemplate;

    private Class entityClass;

    public BaseHibernateSearchImpl() {
        this.entityClass = ClassUtils.getSuperClassGenricType(getClass(), 0);
    }

    public BaseHibernateSearchImpl(Class<T> entityClass, SessionFactory sessionFactory) {
        this.entityClass = ClassUtils.getSuperClassGenricType(getClass(), 0);
        this.sessionFactory = sessionFactory;
    }

    protected final Session getSession() {
        return HibernateUtils.getSession(sessionFactory);
    }

    protected final DefaultHibernateTemplate getHibernateTemplate() {
        return hibernateTemplate;
    }

    @Override
    public QueryBuilder getQueryBuilder() {
        // TODO Auto-generated method stub
        return Search.getFullTextSession(getSession()).getSearchFactory().buildQueryBuilder().forEntity(entityClass).get();
    }

    @Override
    public void updateIndex(Serializable id) {
        // TODO Auto-generated method stub
        Session session = getSession();
        Object object = session.get(entityClass, id);
        Search.getFullTextSession(session).index(object);
    }

    @Override
    public void updateAllIndex() {
        // TODO Auto-generated method stub
        updateAllIndex(DEFAULT_BATCH_SIZE);
    }

    @Override
    public void updateAllIndex(int batchSize) {
        // TODO Auto-generated method stub
        MassIndexer indexer = Search.getFullTextSession(getSession()).createIndexer(entityClass);
        indexer.batchSizeToLoadObjects(batchSize);
        indexer.start();
    }

    @Override
    public Long count(Query query, Class... clazz) {
        // TODO Auto-generated method stub
        int size = Search.getFullTextSession(getSession()).createFullTextQuery(query, clazz).getResultSize();
        return new Long(size);
    }

    @Override
    public Page searchPage(Page page, Query query, Class... entityClass) {
        // TODO Auto-generated method stub
        FullTextQuery fullTextQuery = Search.getFullTextSession(getSession()).createFullTextQuery(query, entityClass);

        if (page.isAutoCount()) {
            page.setTotalCount(fullTextQuery.getResultSize());
            page.setAutoCount(false);
        }

        fullTextQuery.setFirstResult(page.getFirst() - 1);
        fullTextQuery.setMaxResults(page.getPageSize());
        List list = fullTextQuery.list();
        page.setResult(list);
        return page;
    }

}
